package com.lintf.bot.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lintf.bot.domain.BotDaily;
import com.lintf.bot.domain.constant.Constant;
import com.lintf.bot.domain.dto.BotDailyAddDTO;
import com.lintf.bot.domain.dto.BotDailyLikeListDTO;
import com.lintf.bot.domain.dto.BotDailyListDTO;
import com.lintf.bot.domain.dto.BotDailyUpdateDTO;
import com.lintf.bot.domain.enums.NoticeTypeEnums;
import com.lintf.bot.domain.enums.SysFileTypeEnums;
import com.lintf.bot.domain.vo.BotDailyLikeListVo;
import com.lintf.bot.domain.vo.BotDailyListVo;
import com.lintf.bot.domain.vo.BotDailyOwnListVo;
import com.lintf.bot.mapper.BotDailyMapper;
import com.lintf.bot.notice.NoticeUtils;
import com.lintf.bot.service.IBotDailyLikeService;
import com.lintf.bot.service.IBotDailyService;
import com.lintf.common.core.domain.entity.SysUser;
import com.lintf.common.utils.SecurityUtils;
import com.lintf.common.utils.uuid.IdUtils;
import com.lintf.system.domain.SysFileInfo;
import com.lintf.system.service.ISysFileInfoService;
import com.lintf.system.service.ISysUserService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author lintf
 * @description 针对表【bot_daily】的数据库操作Service实现
 * @createDate 2024-01-07 00:25:53
 */
@Service
public class BotDailyServiceImpl extends ServiceImpl<BotDailyMapper, BotDaily>
        implements IBotDailyService {

    @Autowired
    private ISysFileInfoService sysFileInfoService;
    @Autowired
    private ISysUserService sysUserService;
    @Autowired
    private IBotDailyLikeService botDailyLikeService;
    @Autowired
    private NoticeUtils noticeUtils;

    @Override
    public List<BotDailyListVo> list(BotDailyListDTO dto) {
        LambdaQueryWrapper<BotDaily> wrapper = new LambdaQueryWrapper<>();
        if (dto.getId() != null) {
            wrapper.eq(BotDaily::getId, dto.getId());
        }
        if (StringUtils.isNotEmpty(dto.getSearchValue())) {
            wrapper.like(BotDaily::getContent, dto.getSearchValue());
        }
        if (dto.getGroupId() != null) {
            wrapper.eq(BotDaily::getGroupId, dto.getGroupId());
        } else if (dto.getId() == null) {
            wrapper.eq(BotDaily::getGroupId, 0);
        }
        if (StringUtils.isNotEmpty(dto.getDateSearchValue())) {
            LocalDateTime startTime = LocalDateTime.parse(dto.getDateSearchValue() + "T00:00:00");
            LocalDateTime endTime = LocalDateTime.parse(dto.getDateSearchValue() + "T23:59:59");
            wrapper.ge(BotDaily::getCreateTime, startTime)
                    .le(BotDaily::getCreateTime, endTime);
        }
        wrapper.eq(BotDaily::getIsHide, 0)
                .orderByDesc(BotDaily::getCreateTime);
        Page<BotDaily> page = new Page<>(dto.getPageNum(), dto.getPageSize());
        List<BotDaily> list = baseMapper.selectPage(page, wrapper).getRecords();
        return this.getSysFile(list);
    }

    private List<BotDailyListVo> getSysFile(List<BotDaily> list) {
        LambdaQueryWrapper<SysFileInfo> innerWrapper;
        List<BotDailyListVo> result = new ArrayList<>();
        BotDailyListVo vo;
        for (BotDaily item : list) {
            innerWrapper = new LambdaQueryWrapper<>();
            vo = new BotDailyListVo();
            Integer refId = item.getId();
            BeanUtils.copyProperties(item, vo);
            innerWrapper.eq(SysFileInfo::getRefId, refId)
                    .eq(SysFileInfo::getRefType, SysFileTypeEnums.DAILY.getValue())
                    .orderByAsc(SysFileInfo::getFileIndex);
            List<SysFileInfo> sysFileInfos = sysFileInfoService.list(innerWrapper);
            vo.setSysFileInfos(sysFileInfos);
            BotDailyLikeListDTO listDTO = new BotDailyLikeListDTO();
            listDTO.setRefDailyId(item.getId());
            List<BotDailyLikeListVo> dailyLikes = botDailyLikeService.selectDailyLikeList(listDTO);
            vo.setBotDailyLikes(dailyLikes);
            SysUser sysUser = sysUserService.selectUserById(item.getUserId());
            vo.setAvatar(sysUser.getAvatar());
            vo.setNickName(sysUser.getNickName());
            result.add(vo);
        }
        return result;
    }

    @Override
    public List<BotDailyOwnListVo> ownList(BotDailyListDTO dto) {
        LambdaQueryWrapper<BotDaily> wrapper = new LambdaQueryWrapper<>();
        if (dto.isOwnData()) {
            wrapper.eq(BotDaily::getUserId, SecurityUtils.getUserId())
                    .eq(BotDaily::getGroupId, dto.getGroupId());
        }
        wrapper.orderByDesc(BotDaily::getCreateTime);
        List<BotDaily> list = baseMapper.selectList(wrapper);
        List<BotDailyListVo> result = this.getSysFile(list);
        Map<Integer, Map<Integer, Map<Integer, List<BotDailyListVo>>>> groupedData = result.stream()
                .collect(Collectors.groupingBy(botDaily ->
                                botDaily.getCreateTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDate().getYear(),
                        Collectors.groupingBy(botDaily ->
                                        botDaily.getCreateTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDate().getMonthValue(),
                                Collectors.groupingBy(botDaily ->
                                        botDaily.getCreateTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDate().getDayOfMonth())
                        )
                ));
        List<BotDailyOwnListVo> ownListVos = new ArrayList<>();
        for (Map.Entry<Integer, Map<Integer, Map<Integer, List<BotDailyListVo>>>> yearEntry : groupedData.entrySet()) {
            int year = yearEntry.getKey();
            Map<Integer, Map<Integer, List<BotDailyListVo>>> monthMap = yearEntry.getValue();
            BotDailyOwnListVo innerOwnListVoOfYear = new BotDailyOwnListVo();
            innerOwnListVoOfYear.setKey(year);
            List<BotDailyOwnListVo> ownListOfYear = new ArrayList<>();
            for (Map.Entry<Integer, Map<Integer, List<BotDailyListVo>>> monthEntry : monthMap.entrySet()) {
                int month = monthEntry.getKey();
                Map<Integer, List<BotDailyListVo>> dayMap = monthEntry.getValue();
                BotDailyOwnListVo innerOwnListVoOfMonth = new BotDailyOwnListVo();
                innerOwnListVoOfMonth.setKey(month);
                List<BotDailyOwnListVo> ownListOfMonth = new ArrayList<>();
                for (Map.Entry<Integer, List<BotDailyListVo>> dayEntry : dayMap.entrySet()) {
                    int day = dayEntry.getKey();
                    List<BotDailyListVo> botDailies = dayEntry.getValue().stream().sorted(Comparator.comparing(BotDailyListVo::getCreateTime).reversed()).collect(Collectors.toList());
                    BotDailyOwnListVo innerOwnListVoOfDate = new BotDailyOwnListVo();
                    innerOwnListVoOfDate.setKey(day);
                    innerOwnListVoOfDate.setDailyList(botDailies);
                    ownListOfMonth.add(innerOwnListVoOfDate);
                }
                List<BotDailyOwnListVo> dayCollect = ownListOfMonth.stream().sorted(Comparator.comparing(BotDailyOwnListVo::getKey).reversed()).collect(Collectors.toList());
                innerOwnListVoOfMonth.setDailyOwnList(dayCollect);
                ownListOfYear.add(innerOwnListVoOfMonth);
            }
            List<BotDailyOwnListVo> monthCollect = ownListOfYear.stream().sorted(Comparator.comparing(BotDailyOwnListVo::getKey).reversed()).collect(Collectors.toList());
            innerOwnListVoOfYear.setDailyOwnList(monthCollect);
            ownListVos.add(innerOwnListVoOfYear);
        }
        return ownListVos.stream().sorted(Comparator.comparing(BotDailyOwnListVo::getKey).reversed()).collect(Collectors.toList());
    }

    @Override
    @Transactional
    public void add(BotDailyAddDTO dto) {
        Long userId = SecurityUtils.getUserId();
        String nickName = SecurityUtils.getLoginUser().getUser().getNickName();
        BotDaily botDaily = new BotDaily();
        BeanUtils.copyProperties(dto, botDaily);
        botDaily.setUserId(userId);
//        botDaily.setCreateParams();
        if (baseMapper.insert(botDaily) != 0) {
            List<SysFileInfo> sysFileInfos = dto.getSysFileInfos();
            sysFileInfos.forEach(item -> {
                item.setId(IdUtils.simpleUUID());
                item.setRefType(SysFileTypeEnums.DAILY.getValue());
                item.setRefId(botDaily.getId());
//                item.setCreateParams();
            });
            sysFileInfoService.saveBatch(sysFileInfos);
            String noticeTitle = nickName + "发布了一条" + Constant.DAILY + "分享";
            noticeUtils.systemPush(botDaily.getId(), noticeTitle, NoticeTypeEnums.DAILY_PUBLISH, Constant.DAILY, nickName + "的日常分享", botDaily.getCreateTime(), dto.getGroupId());
        }
    }

    @Override
    public void update(BotDailyUpdateDTO dto) {
        BotDaily botDaily = new BotDaily();
        BeanUtils.copyProperties(dto, botDaily);
//        botDaily.setUpdateParams();
        baseMapper.updateById(botDaily);
    }

    @Override
    public void remove(BotDailyUpdateDTO dto) {
        BotDaily botDaily = new BotDaily();
        BeanUtils.copyProperties(dto, botDaily);
//        botDaily.setUpdateParams();
        baseMapper.deleteById(botDaily);
    }
}




